﻿using System;
using ArithmeticLibrary;

namespace Nolineq.Methods
{
    /// <summary>
    /// Resic rovnice naivnim algoritmem.
    /// </summary>
    public class SimpleMethod : EquationSolver
    {
        #region Constructors

        public SimpleMethod(Function function, double start, double end, double root, double precision, int maxSteps)
            : base(function, start, end, root, precision, maxSteps)
        {
            this.Name = "Jednoduchá metoda";
        }

        #endregion // Constructors

        /// <summary>
        /// Vyresi rovnici Jednoduchou metodou.
        /// </summary>
        /// <param name="start">Zacatek intervalu.</param>
        /// <param name="end">Konec intervalu.</param>
        /// <param name="precision">Presnost.</param>
        /// <returns></returns>
        public override Solution Solve()
        {
            // PREVENCE proti zamrznuti programu. Pocita pocet kroku pri vypoctu.
            int steps = 0;

            // Vytvorime prvni interval.
            double left = Start; 
            double right = Start + Precision;

            // Dokud nenarazime na koren nebo jsme neprosli cely interval
            while (Function.Evaluate(left) * Function.Evaluate(right) > 0 
                && right <= End && steps < MaxSteps)
            {
                steps++;

                left = right;
                right = right + Precision;
            }

            // Pokud skoncil cyklus kvuli teto podmince, nasli jsme koren.
            if (Function.Evaluate(left) * Function.Evaluate(right) <= 0)
            {
                double vysledek = (left + right) / 2;
                return new Solution(vysledek, steps);
            }
            // Jinak to skoncilo kvuli druhe podmince cyklu
            else
            {   
                // Overime, jestli krajni bod je korenem rovnice.
                if (Function.Evaluate(right) == 0)
                    return new Solution(right, steps);

                // Jinak v intervalu nebyl nalezen koren.
                // pokud jsme dosahli maximalniho poctu kroku
                if (steps == MaxSteps)
                    // byla to nevhodne zvolena metoda
                    throw new UnsuitableMethodException("Překročen limit počtu iterací. Zkuste nastavit větší počet iterací, upravit počáteční parametry nebo zvolte jinou metodu.");
                else
                    // jinak proste nebyl koren v intervalu
                    throw new NoSolutionException("V intervalu nenalezen žádný kořen.");
            }
        }
    }
}
